import * as net from "net";
import CommandHandler from "../command/command_handle";
import Control from "../interfaces/control";
import { control_err, control_log } from "../log/logger";
import Tunnel from "../tunnel/tunnel";


export default class TiggerTcpClient implements Control
{
    private client_control: Tunnel;
    private status: boolean; //控制线连接状态
    private registered_command: {cmd:string, cb:(args: number[]) => void}[];

    constructor(options: net.TcpSocketConnectOpts)
    {
        this.client_control = new Tunnel(false, options);
        this.registered_command = new Array<{cmd:string, cb:(args: number[]) => void}>();
    }

    public handleConnectionSuccess(callback: () => void): TiggerTcpClient{
        this.client_control.regConnected((socket: net.Socket) => {
            callback();

            this.status = true;
        });

        this.client_control.getSocket().on("close", (had_err: boolean) => {
            control_log("服务器关闭了连接");
            this.status = false;
        });

        this.client_control.getSocket().on("error", (err:NodeJS.ErrnoException) => {
            this.status = false;
            if(err.errno == -4078)
            {
                //ECONNREFUSED
                control_err("服务器拒接连接", err.errno);
            }
            control_err("连接出现未知错误", -1);
        });

        this.client_control.regBlockRecive((data: Buffer) => {
            for(let i in this.registered_command)
            {
                let cmd = this.registered_command[i];
                CommandHandler.resolveCommand(data, cmd.cmd, cmd.cb);
            }
        });
        return this;
    }

    public getRemoteHost(): string | null {
        if(this.status == true)
        {
            return this.client_control.getSocket().remoteAddress;
        }
        return null;
    }

    public getStatus():boolean {
        return this.client_control.getStatus();
    }

    public registerControlCommand(cmd: string, cb:(args: number[]) => void):TiggerTcpClient {
        //控制命令注册
        if(cmd.length > 256)
        {
            control_err("尝试注册一个长度大于256的命令", -1);
        }
        this.registered_command.push({
            cmd: cmd,
            cb: cb
        });
        return this;
    }

    public pushControlDataToRemote(cmd: string, args: number[]) {
        if(this.getStatus)
        {
            let data:Buffer = CommandHandler.packageCommand(cmd, args);
            this.client_control.writeBlock(data);
        }else{
            control_err("尝试在已关闭的控制线上读写", -1);
        }
    }
}

export function Client(options: net.TcpSocketConnectOpts)
{
    return new TiggerTcpClient(options);
}